﻿#include "FilesSelector.h"
#include "DirectoryModel.h"
#include "FileNameModel.h"
#include <QtCore/QStringListModel>
#include <QtWidgets/QMessageBox>
#include "FilesAddProgress.h"

QFilesSelector::QFilesSelector(QWidget *parent)
	: QDialog(parent)
{
	ui.setupUi(this);
	m_pDirectoryModel = new QDirectoryModel(this);
	ui.treeViewDirectory->setModel(m_pDirectoryModel);
	ui.treeViewDirectory->resizeColumnToContents(0);
	ui.treeViewDirectory->setFocus();
	
	m_pFileNameModel = NULL;
	ui.treeViewFileName->setItemsExpandable(false);
	ui.treeViewFileName->setExpandsOnDoubleClick(false);
	ui.treeViewFileName->setRootIsDecorated(false);

	m_pSelectedFilesModel = new QStringListModel(this);
	ui.listViewSelectedFiles->setModel(m_pDirectoryModel);
	ui.listViewSelectedFiles->setEditTriggers(QAbstractItemView::NoEditTriggers);

	// 初始化按钮状态
	ui.pushButtonAdd->setEnabled(false);
	ui.pushButtonAddAll->setEnabled(false);
	ui.pushButtonAddTree->setEnabled(false);
	ui.pushButtonRemoveTree->setEnabled(false);
	ui.pushButtonRemoveFile->setEnabled(false);
	ui.pushButtonRemoveAll->setEnabled(false);

	connectSlots();
}

QFilesSelector::~QFilesSelector()
{
}

void QFilesSelector::connectSlots()
{
	connect(ui.treeViewDirectory, SIGNAL(clicked(const QModelIndex&)), this, SLOT(treeViewDirectorySlotClicked(const QModelIndex&)));
	connect(ui.treeViewFileName, SIGNAL(clicked(const QModelIndex&)), this, SLOT(treeViewFileNameSlotClicked(const QModelIndex&)));
	connect(ui.treeViewFileName, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(treeViewFileNameSlotDoubleClicked(const QModelIndex&)));
	connect(ui.listViewSelectedFiles, SIGNAL(clicked(const QModelIndex&)), this, SLOT(listViewSelectedFilesSlotClicked(const QModelIndex&)));
	connect(ui.listViewSelectedFiles, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(listViewSelectedFilesSlotDoubleClicked(const QModelIndex&)));
	connect(ui.pushButtonAdd, SIGNAL(clicked()), this, SLOT(pushButtonAddSlotClicked()));
	connect(ui.pushButtonAddAll, SIGNAL(clicked()), this, SLOT(pushButtonAddAllSlotClicked()));
	connect(ui.pushButtonAddTree, SIGNAL(clicked()), this, SLOT(pushButtonAddTreeSlotClicked()));
	connect(ui.pushButtonRemoveTree, SIGNAL(clicked()), this, SLOT(pushButtonRemoveTreeSlotClicked()));
	connect(ui.pushButtonRemoveFile, SIGNAL(clicked()), this, SLOT(pushButtonRemoveFileSlotClicked()));
	connect(ui.pushButtonRemoveAll, SIGNAL(clicked()), this, SLOT(pushButtonRemoveAllSlotClicked()));
}

void QFilesSelector::treeViewDirectorySlotClicked(const QModelIndex& index)
{
	QString qsDirectory = m_pDirectoryModel->filePath(index);
	setCurrentDirectory(qsDirectory);
}

void QFilesSelector::treeViewFileNameSlotClicked(const QModelIndex& index)
{
	if (m_pFileNameModel->isDir(index))
	{
		// 文件夹就让Add按钮不能使用
		ui.pushButtonAdd->setEnabled(false);
	} 
	else
	{
		// 文件的话就让Add按钮可使用
		ui.pushButtonAdd->setEnabled(true);
	}
}

void QFilesSelector::treeViewFileNameSlotDoubleClicked(const QModelIndex& index)
{
	if (m_pFileNameModel->isDir(index))
	{
		// Open
		QString qsDirectory = m_pFileNameModel->filePath(index);
		QModelIndex indexDirectory = m_pDirectoryModel->index(qsDirectory);
		ui.treeViewDirectory->setCurrentIndex(indexDirectory);
		setCurrentDirectory(qsDirectory);
	} 
	else
	{
		// Add
		QString qsFile = m_pFileNameModel->filePath(index);
		addFileToSelected(qsFile);
	}
}

void QFilesSelector::listViewSelectedFilesSlotClicked(const QModelIndex& index)
{
	ui.pushButtonRemoveFile->setEnabled(true);
}

void QFilesSelector::listViewSelectedFilesSlotDoubleClicked(const QModelIndex& index)
{
	if (!index.isValid())
	{
		return;
	}
	QStringList qslFiles = m_pSelectedFilesModel->stringList();
	int nRow = index.row();
	qslFiles.removeAt(nRow);
	setSelectedFiles(qslFiles);
}

void QFilesSelector::pushButtonAddSlotClicked()
{
	QModelIndex index = ui.treeViewFileName->currentIndex();
	QString qsSelectedFile = m_pFileNameModel->filePath(index);
	addFileToSelected(qsSelectedFile);
}

void QFilesSelector::pushButtonAddAllSlotClicked()
{
	QStringList qslFiles;

	QString qsCurrentDirectory = m_pFileNameModel->rootPath();
	QStringList qslNameFilters = m_pFileNameModel->nameFilters();

	QDirIterator dir_iterator(qsCurrentDirectory,
		qslNameFilters,
		QDir::Files | QDir::NoSymLinks);
	while (dir_iterator.hasNext())
	{
		dir_iterator.next();
		QFileInfo file_info = dir_iterator.fileInfo();
		QString qsFilePath = file_info.filePath();
		qslFiles.append(qsFilePath);
	}

	addFilesToSelected(qslFiles);
}

void QFilesSelector::pushButtonAddTreeSlotClicked()
{
	QString qsCurrentDirectory = m_pFileNameModel->rootPath();
	QStringList qslSelectedFiles = m_pSelectedFilesModel->stringList();
	QFilesAddProgress dialog(qsCurrentDirectory, qslSelectedFiles, this);
	if (dialog.exec() != QDialog::Accepted)
	{
		return;
	}
	
	QStringList qslFilePath = dialog.getFilesAdd();
	int nCount = qslFilePath.count();
	if (nCount <= 0)
	{
		QMessageBox msgBox(this);
		msgBox.setText(QStringLiteral("No files found."));
		msgBox.setIcon(QMessageBox::Warning);
		msgBox.exec();
		return;
	}

	QString qsText = QString("%1 files will be added to the project.").arg(nCount);
	QMessageBox msgBox(this);
	msgBox.setIcon(QMessageBox::Warning);
	msgBox.setText(qsText);
	msgBox.setInformativeText("OK to continue?");
	msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
	msgBox.setDefaultButton(QMessageBox::Cancel);
	int ret = msgBox.exec();
	if (QMessageBox::Ok != ret)
	{
		return;
	} 
	addFilesToSelected(qslFilePath);
}

void QFilesSelector::pushButtonRemoveTreeSlotClicked()
{
	QStringList qslSelectedFiles = m_pSelectedFilesModel->stringList();
	QString qsCurrentDirectory = m_pFileNameModel->rootPath();
	QStringList qslLeftedFiles;
	QStringList::const_iterator constIterator;
	for (constIterator = qslSelectedFiles.constBegin(); constIterator != qslSelectedFiles.constEnd(); ++constIterator)
	{
		QString qsFile = *constIterator;
		QFileInfo info(qsFile);
		QString qsPath = info.absolutePath();
		if (qsPath == qsCurrentDirectory)
		{
			continue;
		}

		QString qsPathNative = QDir::toNativeSeparators(qsCurrentDirectory);
		if (!qsPathNative.endsWith(QDir::toNativeSeparators(QDir::separator())))
		{
			qsPathNative += QDir::toNativeSeparators(QDir::separator());
		}
		qsPath = QDir::toNativeSeparators(qsPath);
		if ( qsPath.startsWith(qsPathNative))
		{
			continue;
		}
		qslLeftedFiles.append(qsFile);
	}

	int nCount = qslSelectedFiles.count() - qslLeftedFiles.count();
	if (nCount <= 0)
	{
		QMessageBox msgBox(this);
		msgBox.setIcon(QMessageBox::Warning);
		msgBox.setText(QString("The selected directory trees did not contain any project files."));
		msgBox.exec();
		return;
	} 
	else
	{
		QMessageBox msgBox(this);
		msgBox.setIcon(QMessageBox::Warning);
		msgBox.setText(QString("Are you sure you want to remove %1 files in the selected directory trees?").arg(nCount));
		msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
		msgBox.setDefaultButton(QMessageBox::Cancel);
		int ret = msgBox.exec();
		if (QMessageBox::Ok != ret)
		{
			return;
		} 
		setSelectedFiles(qslLeftedFiles);
	}
}

void QFilesSelector::pushButtonRemoveFileSlotClicked()
{
	QModelIndex index = ui.listViewSelectedFiles->currentIndex();
	if (!index.isValid())
	{
		return;
	}
	QStringList qslFiles = m_pSelectedFilesModel->stringList();
	int nRow = index.row();
	qslFiles.removeAt(nRow);
	setSelectedFiles(qslFiles);
}

void QFilesSelector::pushButtonRemoveAllSlotClicked()
{
	QMessageBox msgBox(this);
	msgBox.setIcon(QMessageBox::Warning);
	msgBox.setText(QString("Are you sure you want to remove all files in the selected directory trees?"));
	msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
	msgBox.setDefaultButton(QMessageBox::Cancel);
	int ret = msgBox.exec();
	if (QMessageBox::Ok != ret)
	{
		return;
	} 
	QStringList qslLeftedFiles;
	setSelectedFiles(qslLeftedFiles);
}

void QFilesSelector::setCurrentDirectory(const QString& qsDirectory)
{
	if (NULL == m_pFileNameModel)
	{
		m_pFileNameModel = new QFileNameModel(this);
		ui.treeViewFileName->setModel(m_pFileNameModel);

		// 有当前路径了就可以增加、删除路径
		ui.pushButtonAddAll->setEnabled(true);
		ui.pushButtonAddTree->setEnabled(true);
		ui.pushButtonRemoveTree->setEnabled(true);
	}
	QModelIndex indexFileName = m_pFileNameModel->setRootPath(qsDirectory);

	QStringList qslSelectedFiles = m_pSelectedFilesModel->stringList();
	m_pFileNameModel->updateFilter(qslSelectedFiles);

	ui.treeViewFileName->setRootIndex(indexFileName);
	QString qsRootPath = m_pFileNameModel->rootPath();
	ui.labelCurrentDirectory->setText(qsRootPath);
}

void QFilesSelector::setSelectedFiles(const QStringList& qslFileList)
{
	QStringList qslFiles = qslFileList;
	qslFiles.sort();
	m_pSelectedFilesModel->setStringList(qslFiles);
	QString qsCount = QString("(%1)").arg(qslFiles.count());
	ui.labelSelectedFilesCount->setText(qsCount);
	m_pFileNameModel->updateFilter(qslFiles);

	if (qslFiles.count() > 0)
	{
		ui.pushButtonRemoveAll->setEnabled(true);
	} 
	else
	{
		ui.pushButtonRemoveAll->setEnabled(false);
	}
	ui.pushButtonRemoveFile->setEnabled(false);
}

void QFilesSelector::addFileToSelected(const QString& qsFile)
{
	QStringList qslFiles = m_pSelectedFilesModel->stringList();
	if (qslFiles.contains(qsFile))
	{
		QMessageBox msgBox(this);
		msgBox.setText(QStringLiteral("此文件已存在！"));
		msgBox.setIcon(QMessageBox::Warning);
		msgBox.exec();
		return;
	}
	
	qslFiles.append(qsFile);
	setSelectedFiles(qslFiles);
}

void QFilesSelector::addFilesToSelected(const QStringList& qslFileList)
{
	QStringList qslFiles = m_pSelectedFilesModel->stringList();
	qslFiles += qslFileList;
	setSelectedFiles(qslFiles);
}
